#include "threadMain.h"
#include <string.h>
#include <windows.h>

/*****************************************************/

//valido que este entre 9 y 0

BOOL validoDigito(char caracter)
{
	if ( caracter <= '9' && caracter >= '0')
	return RES_OK;

	return RES_ERROR;
}

/*****************************************************/

/* Funcion para obtener el nombre del comando */

char* CommandToStr(char c)
{
	switch (c)
	{
		case COMANDO_INT: 	 return COMANDO_STR_INT;
		case COMANDO_FLOAT:  return COMANDO_STR_FLOAT;
		case COMANDO_DOUBLE: return COMANDO_STR_DOUBLE;
		case COMANDO_STRING: return COMANDO_STR_STRING;
		case COMANDO_QUIT:   return COMANDO_STR_QUIT;
	}
	return "";
}
/* Final 'Funcion para obtener el nombre del comando */
/*****************************************************/

/* Funcion para verificar si el comando pasado por parametro es valido */
char StrToCommand(char *com)
{
	if (stricmp(com,COMANDO_STR_INT)==0)		return COMANDO_INT;
	if (stricmp(com,COMANDO_STR_FLOAT)==0)	return COMANDO_FLOAT;
	if (stricmp(com,COMANDO_STR_DOUBLE)==0)	return COMANDO_DOUBLE;
	if (stricmp(com,COMANDO_STR_STRING)==0)	return COMANDO_STRING;
	if (stricmp(com,COMANDO_STR_QUIT)==0)	return COMANDO_QUIT;
	return -1;
}
/* Final 'Funcion para verificar si el comando pasado por parametro es valido */
/******************************************************************************/

/* Funcion para verificar si el numero es un entero */
int NumeroEntero(char *nro)
{
	int i,j,k;
	int respuesta=RES_OK;
	int sentido;
	double int_test;
	char tmp_dig[2];

	int_test = 0;
	sentido=0;

				j = strlen(nro)-1;
				for (i=0; i< strlen(nro) && respuesta==RES_OK; i++)
					{
						if( (nro[0]=='+' || nro[0]=='-' ) && sentido==0 ){
						i++;
						sentido=1;
						j--;
						}

						if(validoDigito(nro[i])==RES_OK )
						{	
							tmp_dig[0] = nro[i];
							tmp_dig[1] = '\0';
							k = atoi(tmp_dig);
							int_test = int_test + (k * pow(10,j));							
							
							respuesta=RES_OK;
						}
						else{
							respuesta=RES_ERROR;
						}
					j--;	
					}
				//printf("%f\n",int_test);
				if (int_test > 2147483647) {respuesta=RES_ERROR;} // Se paso del maximo de un int

//	free(naux);

	return respuesta;
}
/* Final 'Funcion para verificar si el numero es un entero */
/***********************************************************/

/* Funcion para verificar si el numero es un float */
int NumeroFlotante(char *nro)
{
	int i;
	int respuesta=RES_OK;
	int sentido;
	int punto;

	sentido=0;
	punto=0;

						for (i=0; i< strlen(nro) && respuesta==RES_OK; i++)
						{
							if( (nro[0]=='+' || nro[0]=='-' ) && sentido==0 ){
								i++;
								sentido=1;
							}
							if(   (  validoDigito(nro[i])==RES_ERROR   && (nro[i]!='.' || punto==1) )==RES_OK )
							{
								if(nro[i]=='.')
								punto=1;
								respuesta=RES_OK;
							}
							else
								respuesta=RES_ERROR;
						}


		return respuesta;
}
/* Final 'Funcion para verificar si el numero es un float */
/**********************************************************/

/* Funcion para verificar si el numero es un doble */
double NumeroDoble(char *nro, char *e)
{
	int i;
	int respuesta=RES_OK;
	int sentido;
	int punto;

	sentido=0;
	punto=0;


						for (i=0; i< strlen(nro) && respuesta==RES_OK; i++)
						{
							if( (nro[0]=='+' || nro[0]=='-' ) && sentido==0 ){
								i++;
								sentido=1;
							}
							if(   (validoDigito(nro[i])==RES_ERROR   && (nro[i]!='.' || punto==1) )==RES_OK )
								{
								if(nro[i]=='.')
								punto=1;
								respuesta=RES_OK;
								}
								else
								respuesta=RES_ERROR;
						}

   *e=respuesta;

	return *nro;
}
/* Final 'Funcion para verificar si el numero es un doble */
/**********************************************************/

/* Funcion para mostrar los parametros */
void MostrarParametros(char tipo, const char *parametro )
{
	int cant;
	char error;
	char *param;
	char *nro;
	char sep[] = " ";
	double d;
	error=RES_ERROR;
	cant=0;

	if (tipo==td_char)
	{
		printf("%s\n",parametro);
		return;
	}

	param=strdup(parametro);

	/* Leo el primer numero */
	nro = strtok( param, sep );
	while( nro != NULL )
	{
		/* Verifico si puedo pasarlo a entero */
		switch (tipo)
		{
		case COMANDO_INT:
			error=NumeroEntero(nro);
			if (error==RES_ERROR)
				printf("X ");
			else
				printf("%d ",atoi(nro));
			break;
		case COMANDO_FLOAT:
			error=NumeroFlotante(nro);
			if (error==RES_ERROR)
				printf("X ");
			else
				//printf("%f ",d);

				printf("%f ",atof(nro));
			break;
		case COMANDO_DOUBLE:
			d=NumeroDoble(nro, &error);
			if (error==RES_ERROR)
				printf("X ");
			else
				printf("%.15f ",atof(nro));
			break;
		default:
			error=RES_ERROR;
		}

		/* Leo el siguiente */
		nro = strtok( NULL, sep );
	}
	printf("\n");
}
/* Final 'Funcion para mostrar los parametros */
/**********************************************/

/* Funcion para validar un numero */
int ValidarNumero(const char *parametro, char tipo )
{
	int cant;
	char error;
	char *param;
	char *nro;
	double d;
	char sep[] = " ";

	cant=0;

	param=strdup(parametro);

	/* Leo el primer numero */
	nro = strtok( param, sep );
	while( nro != NULL )
	{
		error=RES_OK;
		/* Verifico si puedo pasarlo al tipo especifico */
		switch (tipo)
		{
		case COMANDO_INT:
			error=NumeroEntero(nro);
			break;
		case COMANDO_FLOAT:
			error=NumeroFlotante(nro);
			break;
		case COMANDO_DOUBLE:
			d=NumeroDoble(nro, &error);
			break;
		default:
			error=RES_ERROR;
		}

		if (error==RES_OK)
			cant++;
		else
		{
			/* Si uno no es valido, dejo de verificar */
			cant=-1;
			break;
		}

		/* Leo el siguiente */
		nro = strtok( NULL, sep );
	}

	free(param);
	return cant;
}
/* Final 'Funcion para validar un numero */
/*****************************************/

/* Funcion para verificar si todos los caracteres son blancos */
int TodosBlancos(const char *s)
{
	unsigned int i;

	for (i=0;i<strlen(s);i++)
	{
		if (!isspace(s[i]))
			return -1;
	}

	return 0;
}
/* Final 'Funcion para verificar si todos los caracteres son blancos */
/*********************************************************************/

/* Funcion para Verificar si el parametro es valido */
char ParametroValido(char com, const char *param, int *cant)
{
	char error=RES_OK;
	*cant = 0;

	if ((strlen(param)==0) || (TodosBlancos(param)==0))
		return RES_ERROR;

	switch (com)
	{
		case COMANDO_INT:
		case COMANDO_FLOAT:
		case COMANDO_DOUBLE:
			if ((*cant = ValidarNumero(param, com))<0)
			{
				error=RES_ERROR_SINTAXIS;
			}
			break;
		case COMANDO_STRING:
			if (strlen(param)>0)
			{

				*cant = ((strlen(param))*sizeof(char));
			//	*cant = 1;
				error = RES_OK;
			}
			else
				error = RES_ERROR_LONGITUD;
			break;
		default: //COMANDO_QUIT
			if (strlen(param)>0)
				error = RES_ERROR;

	}
 //printf("%d",error);
	return error;
}
/* Final' Verificar si el parametro es valido */
/**********************************************/

/* Funcion para leer una linea de consola */
char *LeerLinea(int *e)
{
	int i, tam;
	char c;
	int pos;
	char *buffer;

	i=1;
	tam=TEXTO_MAXLEN*i;
	buffer= (char*)malloc(sizeof(char)*(tam+1));

	if (buffer==NULL)
	{
		*e=RES_ERROR;
		return NULL;
	}

	strcpy(buffer, "");

	c=getchar();
	pos=0;

	// Leo toda la linea
	while (c!=10)
	{
		buffer[pos++]=c;
		if (pos>=tam)
		{
			i++;
			tam=TEXTO_MAXLEN*i;
			buffer=(char*)realloc(buffer, (sizeof(char)*tam+1));

			if (buffer==NULL)
			{
				*e=RES_ERROR;
				break;
			}
		}

		c=getchar();
	}
	buffer[pos++]=0;

	*e=RES_OK;

	return buffer;
}
/* Final' Funcion para leer una linea de consola */
/*************************************************/

/* Funcion para recibir datos remotos */
void RecibirDatos(void **conexion)
{	char **dato;
	int cantidad;
	int cantRecibida;
	enum tr_tipo_dato tipo;
	CONEXION *Mycon;

	/* Verifico si tengo la conexion disponible para enviar/recibir */
	if (trConexionActiva((CONEXION*)conexion)!=RES_OK) return;

	dato = (char**)malloc(sizeof(char*));
	*dato=NULL;


	Mycon = (CONEXION*)conexion;


	/* Recibo el comando */


	if (trRecibir( (CONEXION*)conexion, &tipo, &cantRecibida, (void*)dato )!=RES_OK)
	{
		printf("No se pueden recibir datos!\n");
		if (*dato!=NULL)
		{
			free(*dato);
			*dato=NULL;
		}
		free(dato);
		Mycon->estado=SOCK_ERROR;
		ExitThread(RES_ERROR);
	}


	/* Recibo todos los comandos y sus parametros */
	while (strnicmp(*dato, COMANDO_STR_QUIT, 4) != 0)


	{

	//Valido parametros
	if (ParametroValido((char)tipo, *dato, &cantidad)!=RES_OK)
		{
			printf(": Parametro no valido\n");
		}
		else
		{
			MostrarParametros((char)tipo, *dato );
			if (cantidad != cantRecibida)
			{
				printf(" No se recibieron todos los parametros\n");
			}
		}


		if (*dato!=NULL)
		{
			free(*dato);
			*dato=NULL;
		}


		/* Verifico si tengo la conexion disponible para enviar/recibir */
		if (trConexionActiva((CONEXION*)conexion)==RES_OK)
		{
			// Recibo el comando //
			if (trRecibir( (CONEXION*)conexion, &tipo, &cantRecibida, (void*)dato )!=RES_OK)
			{
				printf("No se pueden recibir datos!\n");
				if (*dato!=NULL)
				{
					free(*dato);
					*dato=NULL;
				}
				free(dato);
				Mycon->estado=SOCK_ERROR;
				ExitThread(RES_ERROR);
			}
		}
		else
		{
			printf("La conexion esta desactivada\n");
			break;
		}


		Sleep(2);

	}


	/* Libero recursos */
	if (*dato!=NULL)
	{
		free(*dato);
		*dato=NULL;
	}
	free(dato);

}
/* Final 'Funcion para recibir datos remotos */
/*********************************************/

/* Funcion para enviar datos */
void EnviarDatos(void **conexion)
{
	/* td_int, td_char, td_float, td_double */
	char tipo;
	char *comando;
	char *parametro;
	char *buffer;
	char *aux;
	int cantidad;
	int error;
	fflush(stdin);
	buffer=LeerLinea(&error);
	/* Verifico si tengo la conexion disponible para enviar/recibir */


	if (error==RES_ERROR)
	{
		printf("No se puede alocar memoria");
		return;
	}
	/* Leo de consola los comandos */
	while (strnicmp(buffer, COMANDO_STR_QUIT, 4) != 0)
	{
		if (trConexionActiva((CONEXION*)conexion)!=RES_OK)	return;
		aux=strdup(buffer);
		comando=strtok( aux, " " );

		if ((comando!=NULL) && (strlen(comando)<strlen(buffer)))
		{

			if ((tipo=StrToCommand(comando))>=0)
			{

				parametro=buffer+strlen(comando)+1;

				/* Verifico si el parametro ingresado es valido */
				if (ParametroValido(tipo, parametro ,&cantidad)!=RES_OK)
				{
					printf("Parametro invalido. El comando no sera enviado\n");
				}
				else
				{

					/* Verifico si tengo la conexion disponibqle para enviar/recibir */
					if (trConexionActiva((CONEXION*)conexion)!=RES_OK)
					{
						break;
					}

					/* Si fue valido, envio el comando con la cantidad de parametros */
					if (trEnviar( (CONEXION*)conexion, (enum tr_tipo_dato)tipo,
								  cantidad, (void *)parametro )!=RES_OK)
					{
						printf("No se pueden enviar datos!\n");
						free(aux);
						free(buffer);
						ExitThread(RES_ERROR);
					}
					else
					{
						printf("Se enviaron %d %s\n", cantidad, comando);
					}

				}

			}
			else
			{
				printf("El comando no es valido. No sera enviado\n");
			}
		}
		else
		{
			printf("Falta completar el comando o los parametros. No se enviaran datos.\n");
		}


		free(buffer);
		buffer=LeerLinea(&error);

		if (error==RES_ERROR)
		{
			printf("No se puede alocar memoria");
			return;
		}

		free(aux);

		Sleep(5);

	}

	/* Envio el comando QUIT */
	aux=strdup(buffer);
	comando=strtok( aux, " " );

	if (comando!=NULL)
	{
		/* Verifico si tengo la conexion disponible para enviar/recibir */
		if (trConexionActiva((CONEXION*)conexion)==RES_OK)
		{

			if (trEnviar( (CONEXION*)conexion, td_char, 1, comando )!=RES_OK)
			{
				printf("No se pueden enviar datos!\n");
				free(aux);
				free(buffer);
				ExitThread(RES_ERROR);
			}
		}
		else
		{
			printf("La conexion esta desactivada\n");
		}
	}

	/* Libero recursos */
	free(aux);
	free(buffer);

}
/* Final 'Funcion para enviar datos */
/************************************/

